package com.tensquare.user.service;

import java.util.*;
import java.util.concurrent.TimeUnit;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.Selection;

import com.tensquare.user.dao.AccountDao;
import com.tensquare.user.pojo.Account;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import util.IdWorker;

import com.tensquare.user.dao.UserDao;
import com.tensquare.user.pojo.User;

/**
 * 普通用户的服务层
 * 
 * @author Administrator
 *
 */
@Service
public class UserService {

	@Autowired
	private UserDao userDao;
	@Autowired
	private AccountDao accountDao;
	
	@Autowired
	private IdWorker idWorker;
	@Autowired
	private RedisTemplate redisTemplate;
	@Autowired
	private RabbitTemplate rabbitTemplate;
	@Autowired
	BCryptPasswordEncoder encoder;

	/**
	 * 查询全部列表
	 * @return
	 */
	public List<User> findAll() {
		return userDao.findAll();
	}

	
	/**
	 * 条件查询+分页
	 * @param whereMap
	 * @param page
	 * @param size
	 * @return
	 */
	public Page<User> findSearch(Map whereMap, int page, int size) {
		Specification<User> specification = createSpecification(whereMap);
		PageRequest pageRequest =  PageRequest.of(page-1, size);
		return userDao.findAll(specification, pageRequest);
	}

	
	/**
	 * 条件查询
	 * @param whereMap
	 * @return
	 */
	public List<User> findSearch(Map whereMap) {
		Specification<User> specification = createSpecification(whereMap);
		return userDao.findAll(specification);
	}

	/**
	 * 根据ID查询实体
	 * @param id
	 * @return
	 */
	public User findById(String id) {
		return userDao.findById(id).get();
	}

	/**
	 * 增加用户
	 * @param user
	 */
	@Transactional
	public String add(User user) {
		if(userDao.findByNickname(user.getNickname())>0) return user.getId();
		user.setId( idWorker.nextId()+"" );
		String id=user.getId();
		String newpassword="";
		//密码加密
		if(user.getPassword()!=null){
			newpassword = encoder.encode(user.getPassword());//加密后的密码
		}
		user.setPassword(newpassword);

		userDao.save(user);
		return id;
	}

	/**
	 * 修改用户
	 * @param user
	 */
	@Transactional
	public void update(User user) {
		String newpassword = encoder.encode(user.getPassword());
		user.setPassword(newpassword);
		userDao.save(user);
	}

	/**
	 * 删除用户
	 * @param id
	 */
	@Transactional
	public void deleteById(String id) {
		userDao.deleteById(id);
	}

	/**
	 * 动态条件构建
	 * @param searchMap
	 * @return
	 */
	private Specification<User> createSpecification(Map searchMap) {

		return new Specification<User>() {

			@Override
			public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> predicateList = new ArrayList<Predicate>();
                // ID
                if (searchMap.get("id")!=null && !"".equals(searchMap.get("id"))) {
                	predicateList.add(cb.like(root.get("id").as(String.class), "%"+(String)searchMap.get("id")+"%"));
                }
                // 手机号码
                if (searchMap.get("mobile")!=null && !"".equals(searchMap.get("mobile"))) {
                	predicateList.add(cb.like(root.get("mobile").as(String.class), "%"+(String)searchMap.get("mobile")+"%"));
                }
                // 密码
                if (searchMap.get("password")!=null && !"".equals(searchMap.get("password"))) {
                	predicateList.add(cb.like(root.get("password").as(String.class), "%"+(String)searchMap.get("password")+"%"));
                }
                // 昵称
                if (searchMap.get("nickname")!=null && !"".equals(searchMap.get("nickname"))) {
                	predicateList.add(cb.like(root.get("nickname").as(String.class), "%"+(String)searchMap.get("nickname")+"%"));
                }
                // 性别
                if (searchMap.get("sex")!=null && !"".equals(searchMap.get("sex"))) {
                	predicateList.add(cb.like(root.get("sex").as(String.class), "%"+(String)searchMap.get("sex")+"%"));
                }
                // 头像
                if (searchMap.get("avatar")!=null && !"".equals(searchMap.get("avatar"))) {
                	predicateList.add(cb.like(root.get("avatar").as(String.class), "%"+(String)searchMap.get("avatar")+"%"));
                }
                // E-Mail
                if (searchMap.get("email")!=null && !"".equals(searchMap.get("email"))) {
                	predicateList.add(cb.like(root.get("email").as(String.class), "%"+(String)searchMap.get("email")+"%"));
                }
                // 兴趣
                if (searchMap.get("interest")!=null && !"".equals(searchMap.get("interest"))) {
                	predicateList.add(cb.like(root.get("interest").as(String.class), "%"+(String)searchMap.get("interest")+"%"));
                }
                // 个性
                if (searchMap.get("personality")!=null && !"".equals(searchMap.get("personality"))) {
                	predicateList.add(cb.like(root.get("personality").as(String.class), "%"+(String)searchMap.get("personality")+"%"));
                }
				
				return cb.and( predicateList.toArray(new Predicate[predicateList.size()]));

			}
		};

	}

	/**
	 * 发送短信验证码
	 * @param mobile 手机号
	 */
	public void sendSms(String mobile){
		//1.生成6位短信验证码
		Random random=new Random();
		int max=999999;//最大数
		int min=100000;//最小数
		int code = random.nextInt(max);//随机生成
		if(code<min){
			code=code+min;
		}
		//另一种简单的写法
		//String random1 = RandomStringUtils.random(6);
		//System.out.println(mobile+"收到验证码是："+code);	//这里没有使用消息队列，所以是手动消费
		//2.将验证码放入redis
		redisTemplate.opsForValue().set("smscode_"+mobile, code+"" ,5, TimeUnit.MINUTES );//五分钟过期
		//3.将验证码和手机号发动到rabbitMQ中
		Map<String,String> map=new HashMap();
		map.put("mobile",mobile);
		map.put("code",code+"");
		rabbitTemplate.convertAndSend("sms",map);
	}

	/**
	 * 增加
	 * @param user 用户
	 * @param code 用户填写的验证码
	 */
	@Transactional
	public String add(User user,String code) {
		//判断验证码是否正确,先从缓存中提取验证码
		String syscode = (String)redisTemplate.opsForValue().get("smscode_" + user.getMobile());
		//提取系统正确的验证码
		if(syscode==null){			//这里缓存中还没有存储验证码
			throw new RuntimeException("请点击获取短信验证码");
		}
		if(!syscode.equals(code)){
			throw new RuntimeException("验证码输入不正确");
		}
		user.setId( idWorker.nextId()+"" );
		user.setFollowcount(0);			//关注数
		user.setFanscount(0);			//粉丝数
		user.setOnline(0L);				//在线时长
		user.setRegdate(new Date());	//注册日期
		user.setUpdatedate(new Date());	//更新日期
		user.setLastdate(new Date());	//最后登陆日期

		//密码加密
		String newpassword = encoder.encode(user.getPassword());
		user.setPassword(newpassword);
		userDao.save(user);

		//向账户表中注册用户
		Account account=new Account();
		account.setId(idWorker.nextId()+"");
		account.setUid(user.getId());
		accountDao.save(account);

		return user.getId();
	}

	/**
	 * 根据手机号和密码查询用户
	 * @param mobile
	 * @param password
	 * @return
	 */
	public User findByMobileAndPassword(String mobile,String password){
		User user = userDao.findByMobile(mobile);
		if(user!=null && encoder.matches(password,user.getPassword())){
			return user;
		}else{
			return null;
		}
		//System.out.println(mobile+password);
		//这里暂时不用密码加密
		//User user=userDao.findUserByMobileAndPassword(mobile,password);
		//System.out.println(user);
		//return user;
	}

	//关注某用户，id：当前用户  userId：要关注的用户
	@Transactional
	public void followUser(String id,String userId){
		userDao.updateFollowcount(id);
		userDao.updateFanscount(userId);
		userDao.updaTbFollow(id,userId);
	}

	//删除对某个用户的关注
	@Transactional
	public void deleteFollow(String id, String userId) {
		userDao.deleteFollowCount(id);
		userDao.deleteFancount(userId);
		userDao.deleteTbFollow(id,userId);
	}

	//根据我的id查询我的粉丝们并且分页
	public Page<User> findMyfans(String id, int page, int size) {
		PageRequest pageRequest=PageRequest.of(page-1,size);
		return userDao.findMyfans(id,pageRequest);
	}

	/**
	 * 更新粉丝数
	 * @param x
	 */
	@Transactional
	public void incFanscount(String userid,int x){
		userDao.incFanscount(userid,x);
	}
	/**
	 * 更新关注数
	 * @param x
	 */
	@Transactional
	public void incFollowcount(String userid,int x){
		userDao.incFollowcount(userid,x);
	}

	//查询我的关注
    public Page<User> findMyfollow(String id, int page, int size) {
		PageRequest pageRequest=PageRequest.of(page-1,size);
		return userDao.findMyfollow(id,pageRequest);
    }
	//查询我的关注列表id
	public List<String> findMyfollowid(String id) {
		return userDao.findMyfollowid(id);
	}

	//查询我的账户的信息
	public Account getAccountById(String uid){
		return accountDao.findAccountByUid(uid);
	}
	//修改账户
	@Transactional
	public void updateAccount(Account account) {
		accountDao.save(account);
	}

	//设置用户头像
	@Transactional
    public void setAvator(String uid, String avatar) {
		userDao.setAvator(uid,avatar);
    }
}
